home *** CD-ROM | disk | FTP | other *** search
Text File | 2000-09-28 | 19.4 KB | 885 lines | [TEXT/CWIE] |
- /*
- File: NetSprocketSupport.c
-
- Contains: xxx put contents here xxx
-
- Version: xxx put version here xxx
-
- Copyright: © 1999 by Apple Computer, Inc., all rights reserved.
-
- File Ownership:
-
- DRI: xxx put dri here xxx
-
- Other Contact: xxx put other contact here xxx
-
- Technology: xxx put technology here xxx
-
- Writers:
-
- (cjd) Chris De Salvo
-
- Change History (most recent first):
-
- <SP7> 3/3/99 cjd Updated chat window UI code
- */
-
- //• ------------------------------------------------------------------------------------------ •
- //•
- //• Copyright © 1996 Apple Computer, Inc., All Rights Reserved
- //•
- //•
- //• You may incorporate this sample code into your applications without
- //• restriction, though the sample code has been provided "AS IS" and the
- //• responsibility for its operation is 100% yours. However, what you are
- //• not permitted to do is to redistribute the source as "DSC Sample Code"
- //• after having made changes. If you're going to re-distribute the source,
- //• we require that you make it clear in the source that the code was
- //• descended from Apple Sample Code, but that you've made changes.
- //•
- //• Authors:
- //• Jamie Osborne
- //•
- //• ------------------------------------------------------------------------------------------ •
-
- //• ------------------------------ Includes
-
- #include <ControlDefinitions.h>
- #include <Dialogs.h>
- #include <Fonts.h>
- #include <Lists.h>
- #include <QDOffScreen.h>
- #include <Resources.h>
- #include <Sound.h>
- #include <TextEdit.h>
- #include <TextUtils.h>
-
- #include "CommonStuff.h"
- #include "EventHandler.h"
- #include "NetSprocketSupport.h"
-
- //• ------------------------------ Private Definitions
- //• ------------------------------ Private Types
-
- enum
- {
- kWaitForPlayersDialogID = 1000
- };
-
- enum
- {
- kOKButton = 1,
- kCancelButton,
- kPlayerListLabel,
- kPlayerList,
- kChatWindow,
- kChatTextEntry,
- kStatus
- };
-
- typedef struct DialogInfo
- {
- ListHandle playerList;
- TEHandle teHandle;
- Str32 nameListBuffer[kMaxPlayers];
- } DialogInfo;
-
- //• ------------------------------ Private Variables
- //• ------------------------------ Private Functions
-
- static void GetChooserName(Str255 name);
- static void SendChatText(StringPtr inText, NSpPlayerID inTo);
- static void DoHandleMessage(NSpMessageHeader *inMessage);
- static pascal void PlayerListProc(WindowPtr dialog, SInt16 itemNo);
- static pascal void ChatViewProc(WindowPtr dialog, SInt16 itemNo);
- static void SetDialogtemUserProc(DialogPtr dialog, SInt16 item, UserItemUPP theProc);
- static void WatchForPlayers(DialogPtr dialog);
- static OSStatus SendWelcomeMessage(NSpPlayerID inID);
- static void MakePlayerList(DialogPtr dialog);
- static void SendText(DialogPtr dialog);
-
- static pascal Boolean DialogEventFilter(DialogPtr dialog, EventRecord *event, SInt16 *itemHit);
-
- static void DoHandleChatTextMessage(ChatTextMessage *inMessage, DialogPtr dialog);
- static void PrintPlayerText(StringPtr inText, NSpPlayerID inPlayer, TEHandle inTEHandle);
-
- static void DoHandlePlayerInput(PlayerInputMessage *inMessage);
- static void DoHandleEndGameMessage(void);
- static void DoHandleStartGame(StartGameMessage *inMessage);
- static void DisableDialogItem(DialogPtr theDialog, SInt16 theItem);
-
- //• ------------------------------ Public Variables
-
- NSpGameReference gNetGame = NULL;
- Boolean gIAmHost = false;
- Str31 kNetworkGameName = "\pNetSprocket Game";
- Str31 kJoinDialogLabel = "\pChoose a Game:";
- Str31 kNBPType = "\pInvd"; // This should be the same as kGameID
- NetworkState gNetState;
- Str31 kSeparatorString = "\p: ";
- SInt8 kReturn = '\r';
- Boolean gGotEndGameMessage = false;
- Boolean gReceivedInput;
- Boolean gNetSprocketPresent;
-
- #pragma mark === Utility functions ===
-
- //• -------------------- NetSprocketPresent
- //•
- //• returns TRUE if networking is present, FALSE otherwise
-
- Boolean
- NetSprocketPresent(void)
- {
- return (NSpInitialize != nil);
- }
-
- //• -------------------- GetChooserName
-
- static void
- GetChooserName(Str255 name)
- {
- StringHandle userName;
-
- userName = GetString(-16096);
- FAIL_NIL(userName, "GetString for Chooser Name failed");
-
- CopyPStr(*userName, name);
- ReleaseResource ((Handle) userName);
-
- error:
- return;
- }
-
- #pragma mark === Networking stuff ===
-
- //• -------------------- InitNetworking
-
- Boolean
- InitNetworking(void)
- {
- OSStatus status;
-
- if (! NetSprocketPresent())
- return (false);
-
- //• Initialize NetSprocket
- status = NSpInitialize(kStandardMessageSize, kBufferSize, kQElements, kGameID, kTimeout);
- FAIL_OSSTATUS(status, "NSpInitialize failed");
- if (status != noErr)
- return (false);
-
- gNetState = kSlacking;
-
- return (true);
-
- error:
- return (false);
- }
-
- //• -------------------- ShutdownNetworking
-
- void
- ShutdownNetworking(void)
- {
- OSStatus status;
-
- if (gNetGame)
- status = NSpGame_Dispose( gNetGame, kNSpGameFlag_ForceTerminateGame );
-
- gNetState = kSlacking;
- gNetGame = NULL;
- }
-
-
- //• -------------------- DoHostGame
- //•
- //• Returns TRUE if the user says OK (and NetSprocket doesn't return an error), false otherwise
-
- Boolean
- DoHostGame(void)
- {
- OSStatus status = noErr;
- NSpProtocolListReference theList = NULL;
- Str31 playerName, gameName, password;
- Boolean OKHit;
-
- status = NSpProtocolList_New(NULL, &theList);
- FAIL_OSSTATUS(status, "Couldn't create a protocol list");
-
- // Do the host dialog
- GetChooserName(playerName);
- CopyPStr(kNetworkGameName, gameName);
- password[0] = 0;
-
- OKHit = NSpDoModalHostDialog(theList, gameName, playerName, password, NULL);
- if (!OKHit)
- return (false);
-
- // Now host the game
- status = NSpGame_Host(&gNetGame, theList, kMaxPlayers, gameName,
- password, playerName, 0, kNSpClientServer, 0);
-
- FAIL_OSSTATUS(status, "NSpGame_Host returned an error");
-
- NSpProtocolList_Dispose(theList);
- gIAmHost = true;
- gNetState = kHosting;
-
- // let all the players join
- OKHit = WaitForAllPlayers();
-
- if (OKHit == false)
- {
- ShutdownNetworking();
- return (false);
- }
- else
- {
- gNetState = kStarting;
- SendStartGame();
- }
-
- return (true);
-
- error:
-
- if (theList)
- NSpProtocolList_Dispose(theList);
-
- return (false);
- }
-
- //• -------------------- DoJoinGame
- //•
- //• Returns TRUE if the user says OK (and NetSprocket doesn't return an error), false otherwise
-
- Boolean
- DoJoinGame(void)
- {
- NSpAddressReference theAddress;
- Str31 name;
- Str31 password;
- OSStatus status;
- Boolean OKHit = true;
-
- GetChooserName(name);
- password[0] = 0;
-
- gIAmHost = false;
-
- theAddress = NSpDoModalJoinDialog(kNBPType, kJoinDialogLabel, name, password, NULL);
- if (theAddress == NULL) // The user cancelled
- return (false);
-
- status = NSpGame_Join(&gNetGame, theAddress, name, password, 0, NULL, 0, 0);
- FAIL_OSSTATUS(status, "NSpGame_Join returned an error");
-
- gNetState = kJoining;
-
- OKHit = WaitForAllPlayers();
- if (OKHit == false)
- {
- gNetState = kSlacking;
- ShutdownNetworking();
- }
-
- return OKHit;
-
- error:
- return (false);
- }
-
- //• -------------------- HandleNetworking
-
- void
- HandleNetworking(void)
- {
- NSpMessageHeader *theMessage;
-
- if (gNetGame == NULL)
- return;
-
- theMessage = NSpMessage_Get(gNetGame);
- if (theMessage != NULL)
- {
- DoHandleMessage(theMessage);
- NSpMessage_Release(gNetGame, theMessage);
- }
- }
-
- //• -------------------- DoHandleMessage
-
- static void
- DoHandleMessage(NSpMessageHeader *inMessage)
- {
- switch (inMessage->what)
- {
- case kNSpPlayerJoined:
- break;
-
- case kNSpPlayerLeft:
- break;
-
- case kChatTextMessage:
- DoHandleChatTextMessage((ChatTextMessage *)inMessage, nil);
- break;
-
- case kStartGameMessage:
- DoHandleStartGame((StartGameMessage *) inMessage);
- break;
-
- case kInputMessage:
- DoHandlePlayerInput((PlayerInputMessage *) inMessage);
- break;
-
- case kEndGameMessage:
- DoHandleEndGameMessage();
- break;
-
- default:
- break;
- }
- }
-
- //• -------------------- WatchForPlayers
-
- static void
- WatchForPlayers(DialogPtr dialog)
- {
- NSpMessageHeader *theMessage;
-
- if (gNetGame == NULL)
- return;
-
- while ((theMessage = NSpMessage_Get(gNetGame)) != NULL)
- {
- if (theMessage->what == kNSpPlayerJoined)
- {
- if (gNetState == kHosting)
- SendWelcomeMessage(((NSpPlayerJoinedMessage *) theMessage)->playerInfo.id);
-
- MakePlayerList(dialog);
- }
- else if (theMessage->what == kNSpPlayerLeft)
- {
- MakePlayerList(dialog);
- }
- else if (theMessage->what == kChatTextMessage)
- {
- DoHandleChatTextMessage((ChatTextMessage *)theMessage, dialog);
- }
- else
- {
- DoHandleMessage(theMessage);
- }
-
- NSpMessage_Release(gNetGame, theMessage);
- }
- }
-
- //• -------------------- SendWelcomeMessage
-
- static OSStatus
- SendWelcomeMessage(NSpPlayerID inID)
- {
- #pragma unused (inID)
- OSStatus status = noErr;
-
- return (status);
- }
-
- #pragma mark === Dialog Manager Cruft
-
- //• -------------------- SetDialogtemUserProc
-
- static void
- SetDialogtemUserProc(DialogPtr dialog, SInt16 item, UserItemUPP theProc)
- {
- Rect r;
- SInt16 itemType;
- Handle itemH;
-
- GetDialogItem(dialog, item, &itemType, &itemH, &r);
- itemH = (Handle) theProc;
- SetDialogItem(dialog, item, itemType, itemH, &r);
- }
-
- //• -------------------- MakePlayerList
-
- static void
- MakePlayerList(DialogPtr dialog)
- {
- SInt16 i;
- Cell theCell;
- NSpPlayerEnumerationPtr players;
- OSStatus status;
- DialogInfo *theInfo = (DialogInfo *) GetWRefCon(dialog);
- ListHandle theList = theInfo->playerList;
-
- LSetDrawingMode(true, theList); // turn on updating
-
- status = NSpPlayer_GetEnumeration(gNetGame, &players);
- FAIL_OSSTATUS(status, "NSpPlayer_GetEnumeration returned an error");
-
- for (i = 0; i < players->count; i++)
- CopyPStr(players->playerInfo[i]->name, theInfo->nameListBuffer[i]);
-
- /* DELETE ALL EXISTING ROWS IN LIST */
- LDelRow(0, 0, theList);
-
- /* ADD NAMES TO LIST */
- if (players->count > 0)
- LAddRow(players->count, 0, theList); // create rows
-
- for (i = 0; i < players->count; i++)
- {
- theCell.h = 0;
- theCell.v = i;
- LSetCell(&theInfo->nameListBuffer[i][1], theInfo->nameListBuffer[i][0], theCell, theList);
- }
-
- NSpPlayer_ReleaseEnumeration(gNetGame, players);
-
- error:
- return;
- }
-
- //• -------------------- WaitForAllPlayers
-
- Boolean
- WaitForAllPlayers(void)
- {
- DialogPtr theDialog = GetNewDialog(kWaitForPlayersDialogID, NULL, (WindowPtr) -1);
- ListHandle playerList;
- SInt16 itemHit;
- Boolean okHit = false;
- Rect r, dataBounds = {0,0,0,1};
- Point cellSize = {0,0};
- SInt16 itemType;
- Handle itemH;
- DialogInfo info;
- TextStyle theStyle;
- ControlHandle theControl;
-
- ModalFilterUPP theFilter = NewModalFilterProc(DialogEventFilter);
- UserItemUPP playerListProc = NewUserItemProc(PlayerListProc);
- UserItemUPP chatViewProc = NewUserItemProc(ChatViewProc);
-
- // NOTE: check okUserItemProcUPP != NULL
-
- if (theDialog == NULL)
- return (false);
-
- SetPort(theDialog);
- SetDialogDefaultItem(theDialog, kOKButton);
- SetDialogCancelItem(theDialog, kCancelButton);
-
- SetDialogtemUserProc(theDialog, kPlayerList, playerListProc);
- SetDialogtemUserProc(theDialog, kChatWindow, chatViewProc);
-
- (void) GetDialogItemAsControl(theDialog, kChatTextEntry, &theControl);
- (void) SetKeyboardFocus(theDialog, theControl, kControlLabelPart);
-
-
- // Now create the list of players
- GetDialogItem(theDialog, kPlayerList, &itemType, &itemH, &r);
- r.right -= 15;
-
- playerList = LNew(&r, &dataBounds, cellSize, 0, theDialog, true,
- false, false, true);
-
- info.playerList = playerList;
-
- // Set up the text edut stuff
- GetDialogItem(theDialog, kChatWindow, &itemType, &itemH, &r);
- InsetRect(&r, 2, 2);
-
- info.teHandle = TEStyleNew(&r, &r);
- TEAutoView(true, info.teHandle);
-
- // Set up the default drawing info
- theStyle.tsFont = kFontIDMonaco;
- theStyle.tsSize = 9;
- theStyle.tsColor.red = 0;
- theStyle.tsColor.green = 0;
- theStyle.tsColor.blue = 0;
- theStyle.tsFace = normal;
- TESetStyle(doAll, &theStyle, true, info.teHandle);
-
- // If we're the joiner, disable the OK button
- if (gNetState == kJoining)
- DisableDialogItem(theDialog, kOKButton);
-
- // Save our custom stuff in the refcon
- SetWRefCon(theDialog, (SInt32) &info);
-
- ShowWindow(theDialog);
- DrawControls(theDialog);
-
- do
- {
- ModalDialog(theFilter, &itemHit);
- } while (itemHit != kOKButton && itemHit != kCancelButton);
-
- LDispose(playerList);
- DisposeDialog(theDialog);
-
- DisposeRoutineDescriptor(theFilter);
- DisposeRoutineDescriptor(playerListProc);
- DisposeRoutineDescriptor(chatViewProc);
-
- okHit = (itemHit == kOKButton || gNetState == kRunning);
-
- return (okHit);
- }
-
- //• -------------------- DisableDialogItem
-
- static void
- DisableDialogItem(DialogPtr theDialog, SInt16 theItem)
- {
- SInt16 theType;
- Rect theRect;
- Handle theHandle;
-
- if (! theDialog)
- return;
-
- GetDialogItem(theDialog, theItem, &theType, &theHandle, &theRect);
-
- if (! theHandle)
- return;
-
- HiliteControl((ControlHandle) theHandle, 255);
- theType |= kItemDisableBit;
- SetDialogItem(theDialog, theItem, theType, theHandle, &theRect);
- }
-
- #pragma mark === Callback Procs ===
-
- //• -------------------- PlayerListProc
-
- static pascal void
- PlayerListProc(WindowPtr dialog, SInt16 itemNo)
- {
- Rect r;
- SInt16 itemType;
- Handle item;
- GrafPtr theWindow = (GrafPtr) dialog;
- DialogInfo *theInfo = (DialogInfo *)GetWRefCon(dialog);
- ListHandle list = theInfo->playerList;
-
- if (itemNo == kPlayerList)
- {
- GetDialogItem(dialog, itemNo, &itemType, &item, &r);
- InsetRect(&r, -1, -1);
- FrameRect(&r);
- LUpdate(theWindow->visRgn, list);
- }
- }
-
- //• -------------------- ChatViewProc
-
- static pascal void
- ChatViewProc(WindowPtr dialog, SInt16 itemNo)
- {
- Rect r;
- SInt16 itemType;
- Handle item;
- DialogInfo *theInfo;
-
- GetDialogItem(dialog, itemNo, &itemType, &item, &r);
- theInfo = (DialogInfo *)GetWRefCon(dialog);
-
- FrameRect(&r);
- InsetRect(&r, 2, 2);
- TEUpdate(&r, theInfo->teHandle);
-
- }
-
- //• -------------------- DialogEventFilter
-
- static pascal Boolean
- DialogEventFilter(DialogPtr dialog, EventRecord *event, SInt16 *itemHit)
- {
- OSErr err;
- CGrafPtr oldPort;
- GDHandle oldGD;
- WindowRef window;
- ModalFilterUPP modalProc;
- Rect itemRect;
- SInt16 key;
- SInt16 thePart;
- Boolean accepted = false;
- Point theP;
- Boolean hit;
- DialogInfo *theInfo;
-
- GetGWorld(&oldPort, &oldGD);
- SetGWorld((CGrafPtr)dialog, nil);
-
- IdleControls(dialog);
-
- WatchForPlayers(dialog);
- if (gNetState == kRunning)
- {
- *itemHit = kOKButton;
- return (true);
- }
-
- switch(event->what)
- {
- case keyDown:
- case autoKey:
- key = event->message & charCodeMask;
- if (key == 0x0D)
- {
- SendText(dialog);
- accepted = true;
- }
- else if (key == '\t')
- {
- if (event->modifiers & shiftKey)
- ReverseKeyboardFocus(dialog);
- else
- AdvanceKeyboardFocus(dialog);
- }
- else
- {
- accepted = false;
- }
-
- break;
-
- case updateEvt:
- if (event->message == (SInt32)dialog)
- {
- // in case a screen saver activates.
- UpdateDialog(dialog, dialog->visRgn);
-
- SetCursor(&qd.arrow);
- }
- break;
-
- case activateEvt:
- accepted = true;
- break;
-
- case mouseDown:
- thePart = FindWindow(event->where,&window);
-
- switch (thePart)
- {
- case inContent:
- theP = event->where;
- GlobalToLocal(&theP);
-
- theInfo = (DialogInfo *)GetWRefCon(dialog);
- itemRect = (*theInfo->playerList)->rView;
-
- // add the scroll bar back in for hit testing (remember we took it out earlier)
- itemRect.right += 16;
-
- // See if they clicked in our list!
- if (PtInRect(theP, &itemRect))
- {
- hit = LClick(theP, nil, theInfo->playerList);
- // if they double-clicked the list, return 1, as if the OK button had been pressed
- if (hit)
- *itemHit = kOKButton;
- else
- *itemHit = kPlayerList;
-
- // tell the Dialog Manager that we handled this click, it can stop searching for a click-owner
- accepted = true;
- }
- break;
-
- case inSysWindow:
- SysBeep(30);
- break;
-
- case inDrag:
- if (window == dialog)
- {
- DragWindow(dialog, event->where,&qd.screenBits.bounds);
- accepted = true;
- }
- break;
- }
- break;
- }
-
- if (false == accepted)
- {
- err = GetStdFilterProc(&modalProc);
- if (err == noErr)
- accepted = CallModalFilterProc(modalProc, dialog, event, itemHit);
- }
-
- SetGWorld(oldPort, oldGD);
-
- return (accepted);
- }
-
- //• -------------------- SendText
-
- static void
- SendText(DialogPtr dialog)
- {
- ControlHandle item;
- Str255 theText;
-
- (void) GetDialogItemAsControl(dialog, kChatTextEntry, &item);
- GetDialogItemText((Handle) item, theText);
- SetDialogItemText((Handle) item, "\p");
- DrawOneControl(item);
-
- if (theText[0] > 0)
- SendChatText(theText, kNSpAllPlayers);
-
- }
-
- #pragma mark =====
-
- //• -------------------- SendChatText
-
- static void
- SendChatText(StringPtr inText, NSpPlayerID inTo)
- {
- ChatTextMessage theMessage;
- OSStatus status;
-
- theMessage.h.to = inTo;
- theMessage.h.what = kChatTextMessage;
- theMessage.h.messageLen = sizeof(ChatTextMessage);
- CopyPStr(inText, theMessage.text);
-
- status = NSpMessage_Send(gNetGame, &theMessage.h, kNSpSendFlag_Junk | kNSpSendFlag_SelfSend);
- }
-
- //• -------------------- SendStartGame
-
- void
- SendStartGame(void)
- {
- StartGameMessage theMessage;
- OSStatus status;
-
- NSpClearMessageHeader(&theMessage.h);
- theMessage.h.to = kNSpAllPlayers;
- theMessage.h.what = kStartGameMessage;
- theMessage.h.messageLen = sizeof(StartGameMessage);
- theMessage.seed = qd.randSeed;
-
- status = NSpMessage_Send(gNetGame, &theMessage.h, kNSpSendFlag_Registered | kNSpSendFlag_SelfSend);
- }
-
- //• -------------------- SendInputState
-
- void
- SendInputState(Boolean left, Boolean right, Boolean fire)
- {
- PlayerInputMessage theMessage;
- OSStatus status;
-
- NSpClearMessageHeader(&theMessage.h);
- theMessage.h.to = kNSpAllPlayers;
- theMessage.h.what = kInputMessage;
- theMessage.h.messageLen = sizeof(PlayerInputMessage);
- theMessage.left = left;
- theMessage.right = right;
- theMessage.fire = fire;
-
- status = NSpMessage_Send(gNetGame, &theMessage.h, kNSpSendFlag_Registered);
- }
-
- //• -------------------- SendEndGame
-
- void
- SendEndGame(void)
- {
- OSStatus status;
- NSpMessageHeader theMessage;
-
- NSpClearMessageHeader(&theMessage);
- theMessage.to = kNSpAllPlayers;
- theMessage.what = kEndGameMessage;
- theMessage.messageLen = sizeof(NSpMessageHeader);
-
- status = NSpMessage_Send(gNetGame, &theMessage, kNSpSendFlag_Registered);
- }
-
- //• -------------------- DoHandleChatTextMessage
-
- static void
- DoHandleChatTextMessage(ChatTextMessage *inMessage, DialogPtr dialog)
- {
- DialogInfo *theInfo;
-
- if (! dialog)
- return;
-
- theInfo = (DialogInfo *)GetWRefCon(dialog);
- PrintPlayerText(inMessage->text, inMessage->h.from, theInfo->teHandle);
- }
-
- //• -------------------- DoHandleStartGame
-
- static void
- DoHandleStartGame(StartGameMessage *inMessage)
- {
- gNetState = kRunning;
- qd.randSeed = inMessage->seed;
- }
-
- //• -------------------- DoHandlePlayerInput
-
- static void
- DoHandlePlayerInput(PlayerInputMessage *inMessage)
- {
- if (gIAmHost)
- {
- gGameKeys.redLeft = inMessage->left;
- gGameKeys.redRight = inMessage->right;
- gGameKeys.redFire = inMessage->fire;
- }
- else
- {
- gGameKeys.greenLeft = inMessage->left;
- gGameKeys.greenRight = inMessage->right;
- gGameKeys.greenFire = inMessage->fire;
- }
- gReceivedInput = true;
- }
-
- //• -------------------- DoHandleEndGameMessage
-
- static void
- DoHandleEndGameMessage(void)
- {
- gGotEndGameMessage = true;
- }
-
- //• -------------------- PrintPlayerText
-
- static void
- PrintPlayerText(StringPtr inText, NSpPlayerID inPlayer, TEHandle inTEHandle)
- {
- NSpPlayerInfoPtr info;
-
- NSpPlayer_GetInfo(gNetGame, inPlayer, &info);
-
- TEInsert(&info->name[1], info->name[0], inTEHandle);
- TEInsert(&kSeparatorString[1], kSeparatorString[0], inTEHandle);
- TEInsert(&inText[1], inText[0], inTEHandle);
- TEInsert(&kReturn, 1, inTEHandle);
-
- //• Select end of the TE text
- TESetSelect(32767L, 32767L, inTEHandle);
-
- //• Scroll it into view if necessary
- TESelView(inTEHandle);
- }
-